package de.global42.clubapp.model;

import java.io.Serializable;
import java.util.Date;
import java.util.Random;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotEmpty;

/**
 * @author lutz
 *
 */
@Entity
public class Client implements Serializable{

   /**
	 * Generated Version UID
	 */
	private static final long serialVersionUID = -6705117137040251530L;
@Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "id", updatable = false, nullable = false)
   private Long id = null;
   @Version
   @Column(name = "version")
   private int version = 0;

   @Column(unique = true)
   @NotNull
   @NotEmpty
   protected String identifier;
   
   @Temporal(TemporalType.TIMESTAMP)
   protected Date registeredOn;
   
   @Temporal(TemporalType.TIMESTAMP)
   protected Date lastActivity;
   
   @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "client")
   protected Set<ClientMission> clientMissions;
   
//   TODO: removed field => client coupons are fetched implicedly through the clientmission
//   @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "client")
//   protected Set<ClientCoupon> clientCoupons;
   
   @ManyToMany(fetch = FetchType.LAZY)
   @JoinTable(	name = "client_venue",
		   		joinColumns = 	@JoinColumn(name = "client_id",referencedColumnName = "id"),
				inverseJoinColumns =	@JoinColumn(name = "venue_id",referencedColumnName = "id"))
   protected Set<Venue> venues;
   
   @Transient
   protected final int identifierLength = 10;
   @Transient
   protected final String identifierAllowedChars = "0123456789abcdefghijklmnopqrstuvwxyz";
   
   public String getIdentifier() {
	return identifier;
}

public void setIdentifier(String identifier) {
	this.identifier = identifier;
}

public void setIdentifier() {
	setIdentifier(getRandomIdentifier());
}

/**
 * @return a randomly generated string which can be used as identfifier
 * WARNING: no unique check has been done yet
 */
private String getRandomIdentifier() {
	StringBuffer buffer = new StringBuffer();
	Random random = new Random();
	
	for(int i = 0; i < this.identifierLength; i++) {
		buffer.append(this.identifierAllowedChars.charAt(random.nextInt(this.identifierAllowedChars.length())));
	}
	
	return buffer.toString();
}

public Date getRegisteredOn() {
	return registeredOn;
}

public void setRegisteredOn(Date registeredOn) {
	this.registeredOn = registeredOn;
}

public void setRegisteredOn() {
	   setRegisteredOn(new Date());
}

public Date getLastActivity() {
	return lastActivity;
}

public void setLastActivity(Date lastActivity) {
	this.lastActivity = lastActivity;
}

public void setLastActivity() {
	setLastActivity(new Date());
}

public Set<ClientMission> getClientMissions() {
	return clientMissions;
}

public void setClientMissions(Set<ClientMission> clientMissions) {
	this.clientMissions = clientMissions;
}

//public Set<ClientCoupon> getClientCoupons() {
//	return clientCoupons;
//}
//
//public void setClientCoupons(Set<ClientCoupon> clientCoupons) {
//	this.clientCoupons = clientCoupons;
//}

public Set<Venue> getVenues() {
	return venues;
}

public void setVenues(Set<Venue> venues) {
	this.venues = venues;
}

public Long getId()
   {
      return this.id;
   }

   public void setId(final Long id)
   {
      this.id = id;
   }

   public int getVersion()
   {
      return this.version;
   }

   public void setVersion(final int version)
   {
      this.version = version;
   }

   public String toString()
   {
      String result = "";
      if (id != null)
         result += id;
      return result;
   }

   @Override
   public boolean equals(Object that)
   {
      if (this == that)
      {
         return true;
      }
      if (that == null)
      {
         return false;
      }
      if (getClass() != that.getClass())
      {
         return false;
      }
      if (id != null)
      {
         return id.equals(((Client) that).id);
      }
      return super.equals(that);
   }

   @Override
   public int hashCode()
   {
      if (id != null)
      {
         return id.hashCode();
      }
      return super.hashCode();
   }
}